﻿using System.Diagnostics;

using Game.Actions;
using Game.Command.Internal;
using Game.Common;
using Game.Level;
using Game.Map;
using Game.Map.Extensions;
using Game.PathFinder;
using Game.StateMachine;

namespace Game.Ai.Internal.States.Patrol
{
    class StateIdAttack : StateId
    {
        public StateIdAttack() : base("Attack") {}
    }
    
    class AttackState : State
    {
        private readonly ActionExecutor _actionExecutor;
        
        public AttackState(ActionExecutor actionExecutor)
            : base(new StateIdAttack())
        {
            _actionExecutor = actionExecutor;
        }
        
        public override StateId CheckTransitions(object contoller)
        {
            var ai = contoller as AiController;
            var field = AiUtil.FindOther(ai);
            if (field == null)
            {
                return new StateIdPersue();
            }

            Debug.Assert(ai != null, "ai != null");
            var attackingField = ai.GameMapView.FindItem(ai.Vehicle);
            var finder = FinderFactory.Create(ai.GameMapView, attackingField, field);
            var path = finder.Find();

            if (path == null || path.Distance > 1)
            {
                return new StateIdPersue();
            }
            
            return new StateIdAttack();
        }
        
        public override void DoTurn(
            IGameMapView view, 
            GameLevels levels,
            object contoller, 
            GameTurn turn)
        {
            var ai = contoller as AiController;
            var attackedField = AiUtil.FindOther(ai);
            if (attackedField != null)
            {
                Debug.Assert(ai != null, "ai != null");
                var attackingField = ai.GameMapView.FindItem(ai.Vehicle);

                var finder = FinderFactory.Create(ai.GameMapView, attackingField, attackedField);
                var path = finder.Find();

                if (path != null)
                {
                    if (path.Distance <= 1)
                    {
                        var command = new AttackUnitCommand(ai.GameMap, path);
                        _actionExecutor.Execute(view, levels, turn, command);
                    }
                    else
                    {
                        if (path.CalcTerrainCost(ai.GameMap) <= ai.Vehicle.Movement.Value)
                        {
                            var command = Command.Factory.CreateMoveUnitCommand(
                                ai.GameMap, path, ai.Vehicle);
                            _actionExecutor.Execute(view, levels, turn, command);
                        }
                    }
                }
            }
        }

    }
}
